import numpy as np
import cPickle as pickle

#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Meta( object ):

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __init__( self, name, type = "NUMERIC" ):
		self.setOrgName( name )
		self.setType( type )
		self.select = 1

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def setOrgName( self, name ):
		self.orgName = name;
		self.name = name.upper()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getOrgName( self ):
		return self.orgName

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setName( self, name ):
		self.name = name.upper()


	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getName( self ):
		return self.name		

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setType( self, type = 'STRING' ):
		self.type = type.upper() 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getType( self ):
		return self.type 	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def selected( self ):
		self.select = 1

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def unselected( self ):
		self.select = 0

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def isSelected( self ):
		return self.select
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def save( self, outfile, extra = None ):
		savedFields = { "orgName": self.orgName, "name": self.name, 
						"type": self.type } 
		outfh = open(outfile,"wb")		
		if extra:
			extra.update( savedFields )
			savedFields = extra
		pickle.dump( savedFields,  outfh )
		outfh.close()
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def load( self, infile, extra = None ):
		infh = open(infile,"rb")
		loadFields = pickle.load( infh )
		infh.close()

		builtinFields = ["orgName","name","type"]
		for field in builtinFields:
			setattr(self, field, loadFields[field] )
			del loadFields[field]
		if extra:
			setattr(self, "params", loadFields )
#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Attribute( Meta ):

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __init__( self, name, type = "Numeric", value = None ):
		Meta.__init__(self, name, type )
		self.values = [ ]
		if value:		
			self.addValue( value )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __del__( self ):
		del self.values

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def __len__( self ):
		return len( self.values )	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __iter__( self ):
		return self.values.__iter__()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************			
	def __setitem__( self, index ,value ):
		if index < 0 : return None
		if index < len( self.values ):
			self.values[ index ] = value
		else:
			return None;
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __getitem__( self, index ):
		return self.values[ index ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def addValue( self, value ):
		if value is not None:
			self.values.append( value )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def popValue( self ):
		if len( self.values ):
			return self.values.pop()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def clearValues( self ):
		self.values = [ ]
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def setValue(self, index ,value ):
		if index < 0 : return None
		if index < len( self.values ):
			self.values[ index ] = value
		else:
			return None;
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getValue(self, index ):
		return self.values[ index ] 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def firstValue( self ):
		return self.values[ 0 ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def lastValue( self ):
		return self.values[ -1 ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getValues( self ):
		return self.values

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def size( self ):
		return len( self.values )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def isEmpty( self ):
		return 1 if len( self.values ) else 0


#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Model( Meta ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __init__( self, name = "Model", type = "Model" ):
		Meta.__init__(self, name, type )
		self.defaultparams = { }
		self.params = { }

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __del__( self ):
		del self.defaultparams
		del self.params
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def setDefaultParams( self, **params ):
		self.defaultparams = params.copy()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getDefaultParams( self ):
		return self.defaultparams


	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def resetToDefaultParams( self ):
		self.params = self.defaultparams.copy()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setParams( self, **params ):
		for param in params.keys():
			self.params[ param.upper() ] = 	params[ param ]	
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getParams( self ):
		return self.params

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def setParam( self, param, value ):
		param = param.upper()
		self.params[ param ] = value		
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def getParam( self, param ):
		param = param.upper()
		return 	self.params[ param ] if self.params.has_key( param ) else None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def hasParam( self, param ):
		param = param.upper()
		return self.params.hasKey( param )
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def listParmas( self ):
		return self.params.items( )
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def saveModel( self, filename ):
		self.save( filename, self.params )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def loadModel( self, filename ):
		self.load( filename, extra = True )

#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Field( Attribute ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __init__( self, name, type = "Numeric", value = None ):
		Attribute.__init__(self, name, type, value )
		self.values = [ ]
		self.addValue( value )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __del__( self ):
		del self.values

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def hasValue( self, value ):
		if not len( self.values ) or value is None: return None
		return True if value in self.values else None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def addValue( self, value ):
		if value is not None:
			if self.hasValue( value ) is not None:
				self.values.append( value )
			return self.values.index( value )
		else:
			return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def indexOfValue( self, value ):
		if self.hasValue( value ) is not None:
			return self.values.index( value )
		else:
			return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getIndices( self, name ):
		if not len( self.values ): return None
		return dict( [ ( self.values( elem), elem ) for elem in self.values ] )

#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class MetaList( object ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __init__( self, metanames = [ ] ):
		self.select = 1
		self.metas = [ ]
		self.metaindex = { }
		for name in metanames:
			self.add( name )
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __del__( self ):
		del self.metas
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def calIndex( self ):
		i = 0
		for meta in self.metas:
			self.metaindex[ meta.name ] = i
			i += 1 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setList( self, metas ):
		self.metas = metas 
		self.refresh( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getList( self ):
		return self.metas

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def clearList( self ):
		self.metas = [ ]
		self.refresh()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def refresh( self ):
		self.metaindex = { }
		self.calIndex( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def index( self, name ):
		if name is None: return -1 
		name = name.upper()
		return self.metaindex[ name ] if self.metaindex.has_key( name ) else None

	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def search( self, name ):
		indexOfMeta =  self.index( name )
		return self.metas[ indexOfMeta ] if indexOfMeta is not None else None
	


	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def exist( self, name ):
		indexOfMeta =  self.index( name )
		return 1 if indexOfMeta is not None else 0
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getMeta( self, name ):
		return self.search( name )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def get( self, indexOfMeta ):
		if indexOfMeta is None : return None
		if indexOfMeta < len( self.metas ):
			return self.metas[ indexOfMeta ]
		else:
			return None;
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def add( self ,name ):
		indexOfMeta =  self.index( name )
		if indexOfMeta is None:
			meta = Meta( name )
			self.metas.append( meta )
			self.calIndex()
			return meta

		return 0
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def pop( self ):
		if len( self.metas ):
			self.metas.pop()
			self.refresh( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def rename( self, oldname, newname ):
		meta =  self.search( oldname )		
		if meta is not None: 
			meta.setName( newname ) 
			self.refresh( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def first( self ):
		if len( self.metas ):
			return self.metas[ 0 ]
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def last( self ):
		if len( self.metas ):
			return self.metas[ -1 ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def size( self ):
		return len( self.metas )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def selected( self, name ):
		meta =  self.search( name )		
		if meta is not None: 
			meta.selected() 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def unselected( self, name ):
		meta =  self.search( name )		
		if meta is not None: 
			meta.selected() 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def isSelected( self):
		meta =  self.search( name )	
		if meta is None	: return 0 
		if meta is not None: 
			return meta.selected() 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __iter__( self ):
		return self.metas.__iter__()
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************			
	def __setitem__( self, name , meta ):
		indexOfMeta =  self.index( name )
		if indexOfMeta is not None :
			self.metas[ indexOfMeta ] = meta
		else:
			return None;
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __getitem__( self, name  ):
		indexOfMeta =  self.index( name )
		if indexOfMeta is not None :
			return self.metas[ indexOfMeta ]
		else:
			return None;

	def __len__( self ):
		return len( self.metas )
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterNames( self ):
		return [ meta.name for meta in self.metas ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterSelNames(self ):
		return [ meta.name for meta in self.metas if meta.select ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterUnSelNames(self ):
		return [ meta.name for meta in self.metas if not meta.select ]


#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Attributes( MetaList ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __init__( self, metanames = [ ] ):
		MetaList.__init__( self, metanames )	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __del__( self ):
		if self.metas is not None:
			for meta in self.metas:
				del meta
			del self.metas

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setAttributes( self, attributes ):
		if( type(attributes) == type([])):
			attributes = Attributes( attributes )
		return self.setList( attributes )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getAttributes( self ):
		return self.meta

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def clearAttributes( self ):
		self.clearList( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def add( self, name, value = None ):	
		attribute = None
		indexOfMeta =  self.index( name )
		if indexOfMeta is None:
			attribute = Attribute( name )
			self.metas.append( attribute )
			self.calIndex(  )
		else:
			attribute = self.metas[ indexOfMeta ]
		
		attribute.addValue( value ) 
		return 	attribute

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def addAttribute( self, name, value = None ):
		return self.add( name, value )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def addValueOfAttr( self, name , value = None ):
		return self.add( name, value )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getAttribute( self , name ):
		return self.getMeta( name )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def popAttribute( self ):
		self.pop( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def clearValuesOfAttr( self, name ):
		indexOfMeta =  self.index( name )
		if indexOfMeta is not None:
			attribute = self.metas[ indexOfMeta ]
			attribute.clearValues()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def numOfValue( self, name ):
		indexOfMeta =  self.index( name )
		if indexOfMeta is not None:
			attribute = self.metas[ indexOfMeta ]
			return attribute.size()
		else:
			return 0
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterAttrNames(self ):
		return [ meta.name for meta in self.metas ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterSelAttrNames(self ):
		return [ meta.name for meta in self.metas if meta.select ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterUnSelAttrNames(self ):
		return [ meta.name for meta in self.metas if not meta.select ]





#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Fields( MetaList ):

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __init__( self, metanames = [ ] ):
		MetaList.__init__( self, metanames )	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __del__( self ):
		if self.metas is not None:
			for meta in self.metas:
				del meta
			del self.metas
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def setFields( self, fields ):
		if type( fields ) == type( [] ):
			fields = Fields( fields)
		return self.setList( fields )	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************		
	def getFields( self ):	
		return self.metas

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def add( self, name, value = None ):	
		field = None
		indexOfMeta =  self.index( name )
		if indexOfMeta is None:
			field = Field( name )
			self.metas.append( field )
			self.calIndex(  )
		else:
			field = self.metas[ indexOfMeta ]
		
		return field.addValue( value ) 
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def addField( self, name ):
		return self.add( name )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def addFields( self, names ):
		for name in names:
			self.add( name )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def popField( self ):
		self.pop( )		

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def getField( self, name ):
		return self.getMeta( name )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def addValueOfField( self, name, value ):
		return self.add( name, value )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def valueIndexOfField( self, name , value = None ):
		field = self.getMeta( name )
		if field is not None:
			if value is None:
				return field.getIndices( )
			else:		
				return field.indexOfValue( value )
		else:
			return None 
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def renameField( self, oldname, newname ):
		self.rename( oldname, newname )	


	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def clearFields( self ):
		self.clearList()
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterFieldNames( self, index = None ):
		if index is None:
			return [ meta.name for meta in self.metas ]
		else:
			return [ self.metas[ i ].name for i in index ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterSelFieldNames(self ):
		return [ meta.name for meta in self.metas if meta.select ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def iterUnSelFieldNames(self ):
		return [ meta.name for meta in self.metas if not meta.select ]

#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Record( object ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __init__( self, attrnames = None ):	
		self.select = 1
		if attrnames is None:
			self.attributes = None
		else:
			self.attributes = Attributes( attrnames )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __del__( self ):
		if self.attributes is not None:
			del self.attributes

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setName( self, name = None):
		self.name = name

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getName( self ):
		return self.name
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setAttributes( self , attributes ):
		self.attributes = attributes
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getAttributes( self ):
		return self.attributes

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def hasAttributes( self ):
		return 1 if self.attributes is not None else 0
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def existAttribute( self, attrName ):
		return self.attributes.exist( attrName )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def addValueOfAttr( self, attrName, attrValue = None ):
		self.attributes.addValueOfAttr( attrName, attrValue )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def clearValuesOfAttr( self, attrName ):
		self.attributes.clearValuesOfAttr( attrName )
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************			
	def setAttrValue( self,attrName, attrValue, index = 0 ):
		attribute = self.attributes.getAttribute( attrName )
		if attribute is not None:
			attribute[ index ] = attrValue
		else:
			return None
		return 1

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************			
	def getAttrValue( self,attrName, index = 0 ):
		attribute = self.attributes.getAttribute( attrName )
		if attribute is not None:
			return attribute[ index ]
		
		return None
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getMultiAttrValue( self, attrNames ):
		return [  self.getAttrValue( name ) for name in attrNames ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def numOfAttr( self ):
		return self.attributes.size( )
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def numOfAttrValue( self, attrName ):
		attribute = self.attributes.getAttribute( attrName )
		if attribute is not None:
			return attribute.size( )
		return 0

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def iterAttrNames( self ):
		return self.attributes.iterAttrNames( )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def selected( self ):
		self.select = 1

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def unselected( self ):
		self.select = 0

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def isSelected( self):
		return self.select

#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Instance( Record ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __init__( self , dataset, usenp = False ):
		Record.__init__( self, None ) 
		self.dataset = dataset
		self.usenp = usenp
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __del__( self ):
		del self.dataset
		del self.dataline
		Record.__del__( self )
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __iter__( self ):
		return self.dataline.__iter__()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************			
	def __setitem__( self, index ,value ):
		self.dataline[ index ] = value
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __getitem__( self, index ):
		return self.dataline[ index ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __len__( self ):
		return len( self.dataline )	

	def __str__( self ):
		return "Dataline:[ length = %d ]\n" % len( self.dataline )

	def __repr__( self ):
		return "Dataline:[ length = %d ]\n" % len( self.dataline )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setDataset( self, dataset ):
		self.dataset = dataset

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getDataset( self ):
		return self.dataset

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def hasDataset( self ):
		return True if self.dataset is not None else False

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setDataline(self,  dataline ):
		if self.usenp:
			self.dataline = np.array( dataline )
		else:
			self.dataline = dataline
			
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getDataline( self ):
		return self.dataline

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def appendValue( self, value = None  ):
		if self.usenp: 
			if value is None: value = np.nan
			self.dataline = np.append( self.dataline, value )
		else:
			self.dataline.append( value )
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def setValue( self, name, value = None ):
		if self.dataset is not None:
			indexOfField = self.dataset.indexOfField( name )
			if indexOfField is not None:
				self.dataline[ indexOfField ] = value

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getValue( self, name  ):
		if self.dataset is not None:
			indexOfField = self.dataset.indexOfField( name )
			if indexOfField is not None:
				return self.dataline[ indexOfField ]
		return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getMultiValues( self, names ):
		if self.dataset is not None:
			indexList = [  self.dataset.indexOfField( name ) for name in names ]
			if None not in indexList:
				return self.dataset[indexList]
		return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def iterValues( self ):
		if self.dataset is not None:
			return [ value for value in self.dataline ]
		else:
			return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def iterMultiValues( self, names ):
		values =  self.getMultiValues( name )
		if values is not None:
			return [ value for value in values ]
		else:
			return None

	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def size( self ):
		if self.dataset is not None:
			return self.dataset.numOfField( )
		return 0
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getTargetValue( self ):
		if self.dataset.targetIndex is None:
			return None
		else:
			return self.dataline[ self.dataset.targetIndex ]
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def subline( self, index, reverse = None ):
		size = self.size()
		if size == 0 or len( index ) > size:
			return None
		if reverse is not None:
			allIndex = range( size  )
			for i in index:
				del allIndex[ i ]
			index = allIndex
		instance = Instance( self.dataset, self.usenp )
		dataline = [ self.dataline[i] for i in index ]
		instance.setDataline( dataline )
		return instance
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************				
	def clone( self ):
		if self.size() == 0:
			return None
		instance = Instance( self.dataset, self.usenp )
		instance.setDataline( self.dataline[:] )
		return instance
	
	def show( self ):
		print self.dataline
#*****************************************************************************
# PURPOSE: 
# USAGE:   
# PASSED ARGS:  
# RETURN ARGS: 
# Error - Fail Error Message
#*****************************************************************************
class Instances( Record ):
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __init__( self, fieldnames = [ ], usenp = None  ):
		Record.__init__( self, [ ] ) 
		self.fields = Fields( fieldnames )
		self.targetIndex = None
		self.instances = [ ]
		self.usenp = usenp
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __del__( self ):
		del self.fields
		for instance in self.instances:
			del instance
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def __iter__( self ):
		return self.instances.__iter__()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************			
	def __setitem__( self, index , instance ):
		if index < len( self.instances ):
			if type( instance ) == type([ ]):
				newInstance = Instance( self, self.usenp )
				newInstance.setDataline( instance )
				self.instances[ index ] = newInstance 
			else:
				instance.setDataset( self )
				self.instances[ index ] = instance
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __getitem__( self, index ):
		return self.instances[ index ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************	
	def __len__( self ):
		return len( self.instances )	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def __str__( self ):
		return "Fields: %s\nDataset:[ size = %d x %d ]\n" % ( " ".join( self.iterFieldNames() ), \
														         self.rows(), self.cols( ) ) 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# $sError - Fail Error Message
	#*****************************************************************************
	def __repr__( self ):
		return "Fields: %s\nDataset:[ size = %d x %d ]\n" % ( " ".join( self.iterFieldNames() ),\
														         self.rows(), self.cols( ) ) 
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setFields( self, fields ):
		if fields is not None: 
			if( type( fields ) == type([]) ):
				self.fields = Fields( fields )
			else:
				self.fields = fields

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getFields( self ):
		return self.fields

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getField( self, name ):
		return self.fields.getField( name ) if self.fields.exist( name ) else None

	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def addField( self, name ):
		if self.fields is not None:
			if( not self.fields.exist( name )):
				self.fields.addField( name )
				if( self.instances is not None ):
					for instance in self.instances:
						instance.appendValue()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def popField( self ):
		if self.fields is not None and len( self.fields ):
			self.fields.pop()

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def indexOfField( self, name ):
		if self.fields is not None:
			return self.fields.index( name )
		else:
			return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def numOfField( self ):
		if self.fields is not None:
			return self.fields.size( )
		else:
			return 0
			
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setUseNP( self, usenp = None ):
		self.usenp = usenp

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def getUseNP( self ):
		return self.usenp
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def isUseNP( self ):
		return True if self.usenp else False
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def setTargetIndex( self, index = -1 ):
		self.targetIndex = index

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def getTargetIndex( self ):
		return self.targetIndex 

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def hasTargetIndex( self ):
		return 1 if self.targetIndex is not None else 0

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getNonTargetIndex( self ):
		if self.targetIndex is not None:
			nonTargetFilter = np.ones( self.cols(), dtype=bool)
			nonTargetFilter[ self.targetIndex ] = False
			ind = np.arange(self.cols())		
			nonTargetIndex = ind[ nonTargetFilter ]
			if self.usenp:
				return nonTargetIndex
			else:	
				return nonTargetIndex.tolist()
		return None
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def addInstance( self, instance  ):	
		if type( instance ) == type([ ]):
			newInstance = Instance( self, self.usenp )
			newInstance.setDataline( instance )
			self.instances.append( newInstance )
		else:
			instance.setDataset( self )
			self.instances.append( instance )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def popInstance( self ):
		if self.instances is not None and index < len( self.instances ):
			self.instances.pop()


	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def removeInstance( self, index ):
		if self.instances is not None and index < len( self.instances ):
			del self.instances[ index ]

	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def removeInstanceFrom( self, start, end ):
		if self.instances is not None:
			if start < end and end < len( self.instances ):
				for index in range( start, end + 1 ): 
					del self.instances[ index ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def setInstances( self, instances ):
		self.instances = instances
		for instance in instances:
			instance.setDataset( self )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def getInstances( self, instances ):
		return self.instances

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def mergeInstances( self, instances):
		if self.instances is None:
			self.instances = [ ]
		for instance in instances:
			instance.setDataset( self )
			self.instances.append( instance )
			
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************				
	def clearInstances( self ):		
		self.instances = [ ]
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def firstInstance( self ):
		if self.instances is not None and index < len( self.instances ):
			return self.instances[ 0 ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def lastInstance( self ):	
		if self.instances is not None and index < len( self.instances ):
			return self.instances[ -1 ]

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def setColValues( self , name , value ):
		if self.instances is not None and self.fields.exist( name ):
			if type( value ) == type([]):
				for i in range(len(value)):
					self.instances[i].setValue( name , value )
			else:
				for instance in self.instances:
					instance.setValue( name , value )
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getColValues( self, name ):
		if self.instances is not None and self.fields.exist( name ):
			index = self.indexOfField( name )
			return [ instance[ index ] for instance in self.instances ]
		else:
			None
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def size( self ):
		if self.instances is not None:
			return len( self.instances )
		else:
			return 0
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def rows( self ):
		if self.instances is not None:
			return len( self.instances )
		else:
			return 0

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def cols( self ):
		if self.fields is not None:
			return len( self.fields )
		else:
			return 0

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def iterFieldNames( self, index = None  ):
		if self.fields is not None:
			return self.fields.iterFieldNames( index )
		else:
			return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def iterSelFieldNames( self ):
		if self.fields is not None:
			return self.fields.iterSelFieldNames( )
		else:
			return None
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************	
	def iterUnSelFieldNames( self ):
		if self.fields is not None:
			return self.fields.iterUnSelFieldNames( )
		else:
			return None
	

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def __creatSubIndex( self,index, reverse = None ):
		cols = self.cols()
		colIndex = index 
		
		# Create Index			
		if reverse is not None and len(colIndex) != cols:
			colIndex = range( cols )
			for i in index:
				del colIndex[ i ]	
		return colIndex
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def emptySet( self, index, reverse = None ):		
		if self.cols() == 0:
			return None
		
		colIndex = 	self.__creatSubIndex( index, reverse )	
		fieldNames = self.iterFieldNames( colIndex );
		if len( fieldNames ) < len( colIndex ):
			return None;
		
		newInstance = Instances( fieldNames, self.usenp )
		#print "qwqewewq", newInstance
		return newInstance
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def subset( self, index, reverse = None ):
		if self.cols() == 0:
			return None
		
		colIndex = 	self.__creatSubIndex( index, reverse )			
		newInstance = self.emptySet( colIndex, reverse );
		if newInstance is None :
			return None

		# Create dataline and add it
		for instance in self.instances:
			dataline = [ instance[ i ] for i in colIndex ]
			newInstance.addInstance( dataline )	
		return 	newInstance
		
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def clone( self ):
		if self.cols() == 0:
			return None
		colIndex = range( self.cols() )	
		return self.subset( colIndex )
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def iterSelInstances( self ):
		if self.instances is not None:
			return [ instance for instance in self.instances if instance.isSelected() ]
		else:
			return None
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def iterUnSelInstances( self ):
		if self.instances is not None:
			return [ instance for instance in self.instances if not instance.isSelected() ]
		else:
			return None

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def filterSelInstances( self ):
		if self.instances is not None:
			newInstances = []
			for instance in self.instances:
				if instance.isSelected( ):
					del instance
				else:
					newInstances.append( instance )
			del self.instances
			self.instances = []
			self.mergeInstances( newInstances )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def filterUnSelInstances( self ):
		if self.instances is not None:
			if self.instances is not None:
				newInstances = []
				for instance in self.instances:
					if not instance.isSelected( ):
						del instance
					else:
						newInstances.append( instance )
				del self.instances
				self.instances = []
				self.mergeInstances( newInstances )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def filterUnSelFields( self ):
		if self.fields is not None:
			selFieldName = self.iterSelFieldNames( )
    		if selFieldName is not None:
				selFieldIndex = [ self.fields.index( name ) for name in selFieldName ]
				for instance in self.instances:
					if self.usenp:
						instance.dataline = instance.dataline[ selFieldIndex ]
					else:
						instance.dataline = [ instance.dataline[ i ] for i in selFieldIndex]
				self.setFields( selFieldName )
				
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def filterSelFields( self ):
		if self.fields is not None:
			unselFieldName = self.iterUnSelFieldNames( )
    		if unselFieldName is not None:
				selFieldIndex = [ self.fields.index( name ) for name in unselFieldName ]
				for instance in self.instances:
					if self.usenp:
						instance.dataline = instance.dataline[ selFieldIndex ]
					else:
						instance.dataline = [ instance.dataline[ i ] for i in selFieldIndex]
				self.setFields( unselFieldName )

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************				
	def toNPInstanses( self ):
		if self.instances is not None \
		   and type(self.instances) == type([]): 
			npinstances = np.array( [ instance for instance in self.instances ] )
			del self.instances
			self.instances = npinstances

	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def toRawInstanses( self ):
		if  self.instances is not None \
			and	type(self.instances) == type(np.array([])):
			rawinstances = self.instances.tolist()
			del self.instances
			self.instances = rawinstances
			
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************
	def getNPArray( self ):
		if self.instances is not None: 	
			return np.array( [ instance.dataline for instance in self.instances ] )
	
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************		
	def getRawArray( self ):
		if self.instances is not None:
			return [ instance.dataline for instance in self.instances ] 
			
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************				
	def show( self ):	
		print self.iterFieldNames()
		for instance in self.instances:
			instance.show()
			
	#*****************************************************************************
	# PURPOSE: 
	# USAGE:   
	# PASSED ARGS:  
	# RETURN ARGS: 
	# Error - Fail Error Message
	#*****************************************************************************			
	def getTargetValues( self, uniq = None ):		
		if not self.hasTargetIndex():
			return None
		targetIndex = self.getTargetIndex();
		values = [ instance[ targetIndex ] for instance in self.instances ]	
		if uniq is not None:
			return list(set(values))
		else:
			return values
